// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include<math.h>
#include<stdlib.h>
//定义两个宏，M代表矩阵的行数，N代表矩阵的列数
#define M 4
#define N 4   
using namespace std;
//flag数组起到标识作用，用来标识某列的数据是否为0，若flag[n]=0,则该列不为0
int flag[M];
int count1[M];//用来存储3行从开头起所具有的数据为0 的元素的个数
//输出矩阵的函数
void print(float(*a)[N])//以下参数都是用float类型，适应范围更广
{
	int i, j;
	for (i = 0; i < M; i++) //二层循环打印
	{
		for (j = 0; j < N; j++)
		{
			if (fabs(a[i][j]) < 0.000001) //先判断是否为零
				a[i][j] = 0;
			cout << a[i][j] << "   ";
		}
		cout << endl;  //一整行打印完，回车，打印下一行
	}
}
//统计矩阵每行从开头起所具有的连续为0的元素的个数并赋给数组count1，例如0 1 2 0 4，则统计出来为1；
 void statistics(float(*a)[N])
{
	int i = 0, j = 0;
	for (i = 0; i<M; i++) //一层的行循环
	{
		int n = 0;
		for (j = 0; j<M; j++)  //二层列循环
			if (fabs(a[i][j])<0.000001)
			{
				n++;
				count1[i] = n;  //若为零，则计数器加一并赋值给数组count1相应元素
			}
			else
			{
				count1[i] = n;
				break;
			}
	}
}
 //交换两行的数据的函数
void exchange(float a[], float b[]) 
{
	float t;//定义临时变量交换数据
	for (int i = 0; i<N; i++)
	{
		t = a[i];
		a[i] = b[i];
		b[i] = t;
	}
}
//使某个数据变为1
void change1(float a[], float b)
{
	for (int i = 0; i<N; i++)
		a[i] /= b;
}
//判定某列的数据是否为0，并将1或0赋给数组flag[];
void judgement(float *p)
{
	for (int i = 0; i<M; i++)
		if (fabs(p[N*i])<0.000001)
			flag[i] = 0;
		else
			flag[i] = 1;
}
//b行的数据减去a行的数据与b行该列数据的乘积，将所得的差值再依次赋给b行的数据
void subtraction(float a[], float b[], float rb)
{
	for (int i = 0; i<N; i++)
		b[i] = b[i] - a[i] * rb;
}
int main()
{
	cout <<"请输入一个" << M << "行" << N << "列的矩阵：" << endl;
	float Matrix[M][N];
	int i = 0, j = 0;
	//初始化赋值
	for (i = 0; i<M; i++)
		for (j = 0; j<N; j++)
			cin >> Matrix[i][j];

	cout << "The original matrix:" << endl;
	print(Matrix);
	cout << endl;
	//核心部分代码
		for (j = 0; j<N; j++)
	{
		//统计每行从开头起所具有的数据为0的元素的个数并赋给数组count1
		statistics(Matrix);

		/*将从行开头起所具有的连续为0的元素多的行放到矩阵的下部,利用了选择排序法的思想，
		先找到最小值，再与首元素交换，该方法在一定程度上减少了交换次数，提高了程序的运行效率;*/
		for (int h = 0; h<M - 1; h++)
		{
			int min = count1[h], tag = h;
			for (int k = h + 1; k <= M - 1; k++)
				if (min>count1[k])
				{
					min = count1[k];
					tag = k;
				}
			exchange(*(Matrix + h), *(Matrix + tag));
		}
		//行交换后重新统计每行从开头起所连续具有的数据为0的元素的个数并赋给数组count1
		statistics(Matrix);
		cout << endl;
		//判定第j列的数据是否为0，并将1或0赋给flag数组
		judgement(*Matrix + j);

		//如果本行前面的数据均为0即count[k]==j(或者该列为第首列)且本行该列的数据不为0，则将该行进行置1运算
		for (int k = 0; k<M; k++)
			if ((j == 0 || count1[k] == j) && (flag[k] == 1))
				change1(*(Matrix + k), Matrix[k][j]);//满足上述条件就将第k行均除以Matrix[k][j]，进行置1运算;
		
		//用来label标记使得其他行变为0的辅助基本行的行号,该行前面的元素为0，该列上的元素为1
		int label = -1;
		for (int k1 = 0; k1<M; k1++)
			//判断条件表示：如果本行前面的数据均为0即count[k]==j(或者该列为第首列)且本行该列的数据不为0
			if ((j == 0 || count1[k1] == j) && (flag[k1] == 1))
			{
				label = k1;
				break;
			}
		if (label != -1)
		{
			for (int k2 = 0; k2<M; k2++)
				if ((k2 != label) && (flag[k2] == 1))
					subtraction(Matrix[label], Matrix[k2], Matrix[k2][j]);
		}
	}
	cout << "原矩阵的行最简型矩阵是：" << endl;
	print(Matrix);
	cout << endl;
	system("pause");
	return 0;
}
